﻿namespace 垃圾回收的示例
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("===== C#垃圾回收教学演示 =====");
            Console.WriteLine("提示：垃圾回收（GC）的核心是自动回收「不再被引用」的对象内存\n");

            // 1. 演示"什么是垃圾"：不再被引用的对象
            DemonstrateGarbageDefinition();

            // 2. 演示GC的自动回收与强制回收
            DemonstrateGcCollection();

            // 3. 演示析构函数与IDisposable（手动释放资源）
            DemonstrateResourceRelease();

            Console.WriteLine("\n===== 演示结束 =====");
            Console.WriteLine("总结：GC自动管理托管资源，非托管资源需通过IDisposable手动释放");
        }

        // 演示"垃圾"的定义：不再被引用的对象
        static void DemonstrateGarbageDefinition()
        {
            Console.WriteLine("\n----- 1. 什么是「垃圾」？ -----");

            // 创建对象并持有引用（此时对象被引用，不是垃圾）
            TrackableObject obj1 = new TrackableObject(1);
            Console.WriteLine("当前：obj1持有对象1的引用（对象1不是垃圾）");

            // 解除引用（对象1不再被任何变量引用，成为"垃圾"）
            obj1 = null;
            Console.WriteLine("执行 obj1 = null 后：对象1不再被引用（成为垃圾，等待GC回收）");
        }

        // 演示GC的自动回收与强制回收
        static void DemonstrateGcCollection()
        {
            Console.WriteLine("\n----- 2. GC如何回收垃圾？ -----");

            // 创建对象2，然后解除引用（成为垃圾）
            TrackableObject obj2 = new TrackableObject(2);
            obj2 = null; // 成为垃圾
            Console.WriteLine("对象2已成为垃圾（等待回收）");

            // GC默认自动触发（时机不确定），这里手动强制触发回收（仅教学用）
            Console.WriteLine("手动触发GC回收（实际开发中无需手动调用）...");
            GC.Collect(); // 强制GC执行回收
            GC.WaitForPendingFinalizers(); // 等待析构函数执行完毕
            Console.WriteLine("GC回收完成（对象2的析构函数应已执行）");

            // 演示：被引用的对象不会被回收
            TrackableObject obj3 = new TrackableObject(3);
            Console.WriteLine("对象3仍被obj3引用（不会被回收）");
            GC.Collect(); // 再次强制回收
            GC.WaitForPendingFinalizers();
            Console.WriteLine("GC回收后：对象3未被回收（因仍有引用）");
        }

        // 演示析构函数与IDisposable（资源释放）
        static void DemonstrateResourceRelease()
        {
            Console.WriteLine("\n----- 3. 资源释放：析构函数 vs IDisposable -----");

            // 情况1：未手动释放资源（依赖GC调用析构函数）
            ResourceHolder resource1 = new ResourceHolder(1);
            resource1 = null; // 成为垃圾
            Console.WriteLine("资源1未手动释放，触发GC回收...");
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Console.WriteLine("结果：GC通过析构函数释放了非托管资源（但时机不确定）");

            // 情况2：手动调用Dispose释放（推荐）
            ResourceHolder resource2 = new ResourceHolder(2);
            Console.WriteLine("手动调用Dispose释放资源2...");
            resource2.Dispose();
            Console.WriteLine("结果：资源2的托管和非托管资源均被立即释放");

            // 情况3：使用using语句（自动调用Dispose，语法糖）
            Console.WriteLine("使用using语句创建资源3...");
            using (ResourceHolder resource3 = new ResourceHolder(3))
            {
                // using作用域内：资源可用
                Console.WriteLine("资源3在using作用域内（正常使用）");
            } // 离开作用域时，自动调用resource3.Dispose()
            Console.WriteLine("结果：using语句自动释放了资源3");
        }
    }
}
